package cn.kilo.infrastructure.persistent.repository;

import cn.kilo.domain.model.login.vo.LoginVo;
import cn.kilo.domain.model.login.vo.RegisterVO;
import cn.kilo.domain.model.login.vo.UserVO;
import cn.kilo.domain.model.order.entity.*;
import cn.kilo.domain.model.order.res.*;
import cn.kilo.domain.model.order.vo.OrderStatusVO;
import cn.kilo.domain.repository.IStrategyRepository;
import cn.kilo.domain.service.order.factory.DefaultFactory;
import cn.kilo.infrastructure.persistent.dao.*;
import cn.kilo.infrastructure.persistent.po.*;
import cn.kilo.infrastructure.persistent.redis.RedissonService;
import cn.kilo.infrastructure.persistent.support.Route;
import cn.kilo.infrastructure.persistent.support.TakeOrder;
import cn.kilo.infrastructure.persistent.support.TimeUtil;
import cn.kilo.infrastructure.persistent.vo.MGuard;
import cn.kilo.infrastructure.persistent.vo.MRider;
import cn.kilo.infrastructure.persistent.vo.MSorter;
import cn.kilo.infrastructure.persistent.vo.MUser;
import cn.kilo.types.common.Constants;
import cn.kilo.types.enums.ResponseCode;
import cn.kilo.types.model.Response;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RScoredSortedSet;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.Guard;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author kilok
 * 仓储服务实现类
 */
@Repository
@Transactional
@Slf4j
public class StrategyRepository implements IStrategyRepository {
    @Resource
    private TakeOrder takeOrder;

    @Resource
    private RedissonService redissonService;

    @Resource
    private IUserDao userDao;

    @Resource
    private IDepartmentDao departmentDao;

    @Resource
    private IOrderDao orderDao;

    @Resource
    private IOrderStaffDao orderStaffDao;

    @Resource
    private IJudgeDao judgeDao;

    @Resource
    private IStaffDao staffDao;

    @Resource
    private IStaffSalaryDao staffSalaryDao;

    @Resource
    private IDepartmentGroupDao departmentGroupDao;

    @Resource
    private IFloorDao floorDao;

    @Resource
    private Route route;

    @Resource
    private IPositionDao positionDao;

    @Resource
    private IMUserDao imUserDao;

    // TODO: 2024/5/8 连接数据库完善仓储服务
    @Override
    public boolean register(RegisterVO registerVO) {
        User one = userDao.queryUserByStuId(registerVO.getStuId());
        if (null != one) {
            return false;
        }
        User user = User.builder()
                .userId(registerVO.getUserId())
                .stuId(registerVO.getStuId())
                .password(registerVO.getPassword())
                .roomNumber(registerVO.getRoomNumber())
                .ridgepole(registerVO.getRidgepole())
                .userName(registerVO.getUserName())
                .floor(registerVO.getFloor())
                .nickName(registerVO.getNickName())
                .grade(registerVO.getGrade())
                .studentInfo(registerVO.getStudentInfo())
                .build();
        int res = userDao.insertUser(user);
        return res != 0;
    }

    @Override
    public Response<?> login(LoginVo loginReq) {
        User user = userDao.queryUserByStuIdAndPassWord(loginReq);
        if (null == user) {
            return Response.<String>builder().code(ResponseCode.UN_ERROR.getCode()).info(ResponseCode.UN_ERROR.getInfo()).data("用户名或密码错误").build();
        }

        return Response.<UserRes>builder().code(
                        ResponseCode.SUCCESS.getCode())
                .info(ResponseCode.SUCCESS.getInfo())
                .data(UserRes.builder()
                        .userId(user.getUserId())
                        .stuId(user.getStuId())
                        .userName(user.getUserName())
                        .image(user.getImage())
                        .roomNumber(user.getRoomNumber())
                        .floor(user.getFloor())
                        .ridgepole(user.getRidgepole())
                        .nickName(user.getNickName())
                        .grade(user.getGrade())
                        .studentInfo(user.getStudentInfo())
                        .firstLogin(user.getFirstLogin())
                        .build()).build();
    }

    @Override
    public Boolean updateUserInfo(UserVO userVO) {
        User user = userDao.queryUserByUserName(userVO.getUserName());
        if (null != user) {
            return false;
        }
        int res = userDao.updateUserInfo(userVO.getUserId(),
                userVO.getNickName(),
                null,
                null,
                null,
                null, null);
        return 0 != res;
    }

    @Override
    public UserEntity queryUserEntityByUserId(String userId) {
        // TODO: 2024/5/8 user->userEntity
        return null;
    }

    @Override
    @Transactional
    public Boolean saveOrder(OrderStatusVO orderStatusVO, String userId) {
        orderStatusVO.setStartTime(orderStatusVO.getNow());
        log.info("orderStatusVO:{}", orderStatusVO);
        String[] split = orderStatusVO.getEnd().split(Constants.UNDERLINE);
        Order order = Order.builder().orderId(
                        orderStatusVO.getOrderId())
                .distance(orderStatusVO.getDistance())
                .orderInfo(orderStatusVO.getOrderInfo())
                .start(orderStatusVO.getStart())
                .end(orderStatusVO.getEnd())
                .ridgepole(orderStatusVO.getRidgepole())
                .floor(Integer.valueOf(split[0]))
                .status(orderStatusVO.getStatus())
                .type(orderStatusVO.getType())
                .userId(userId)
                .orderCode(orderStatusVO.getOrderCode())
                .orderNumber(orderStatusVO.getOrderNumber())
                .price(orderStatusVO.getPrice())
                .startTime(orderStatusVO.getStartTime())
                .dayTime(TimeUtil.getDayTime())
                .build();
        orderStatusVO.setUserId(userId);
        redissonService.setValue(Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderStatusVO.getOrderId(), orderStatusVO);
        redissonService.addObjectToSortedSet(Constants.RedisKey.WAIT_PAY_ORDER, orderStatusVO);
        log.info("order:{}", order);
        return 0 != orderDao.saveOrder(order);
    }

    @Override
    public UserRes getUserInformation(String userId) {
        User user = userDao.queryUserInfoById(userId);
        log.info("user:{}", user);
        return UserRes.builder().userId(
                        user.getUserId()).userName(user.getUserName())
                .image(user.getImage())
                .ridgepole(user.getRidgepole())
                .floor(user.getFloor())
                .roomNumber(user.getRoomNumber())
                .nickName(user.getNickName())
                .studentInfo(user.getStudentInfo())
                .grade(user.getGrade())
                .phoneNumber(user.getPhoneNumber())
                .role(user.getRole())
                .build();
    }

    @Override
    public int getCreateOrderByRidgepole(OrderEntity orderEntity) {

        String cacheKey = Constants.RedisKey.SORTEDSET_DEPARTMENT + Constants.UNDERLINE + orderEntity.getRidgepole();
        log.info("cacheKey:{}", cacheKey);
        RScoredSortedSet<Order> sortedSet = redissonService.getSortedSet(cacheKey);
        return sortedSet.size();

    }

    @Override
    public OrderEntity queryOrderByOrderId(Long orderId) {
        OrderStatusVO orderStatusVO = redissonService.getValue(Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderId);
        OrderEntity orderEntity = new OrderEntity();
        if (null != orderStatusVO) {
            BeanUtils.copyProperties(orderStatusVO, orderEntity);
            return orderEntity;
        }
        Order order = orderDao.queryOrderByOrderId(orderId);
        BeanUtils.copyProperties(order, orderEntity);
        return orderEntity;
    }

    @Override
    public Boolean takeOder(Long orderId, String ridgepole) {
        return takeOrder.takeOrder(orderId, ridgepole);
    }

    @Override
    public OrderStatusVO getOrderStatusEntity(String cacheKey) {
        return redissonService.getValue(cacheKey);
    }

    @Override
    public void savePicture(String url, Long orderId) {
        String cacheKey = Constants.RedisKey.OVER_PICTURE + Constants.UNDERLINE + orderId;
        redissonService.setValue(cacheKey, url);
    }

    @Override
    public boolean checkPicture(Long orderId) {
        String cacheKey = Constants.RedisKey.OVER_PICTURE + Constants.UNDERLINE + orderId;
        return redissonService.isExists(cacheKey);
    }

    @Override
    public OrderStaffEntity takeQueueValue() {
        String cacheKey = Constants.RedisKey.ORDER_STAFF_STOCK;
        RBlockingQueue<OrderStaffEntity> queue = redissonService.getBlockingQueue(cacheKey);
        return queue.poll();
    }

    //更新时间
    @Override
    public void updateOrderStaffStock(OrderStaffEntity orderStaffEntity) {
        OrderStaff orderStaff = new OrderStaff();
        BeanUtils.copyProperties(orderStaffEntity, orderStaff);
        Staff staff = staffDao.getIdByName(orderStaffEntity.getStaffName());
        orderStaff.setStaffId(staff.getStaffId());

        orderStaffDao.update(orderStaff);
    }

    @Override
    public void addOrderStaffStockQueue(OrderStaffEntity orderStaffEntity) {
        String cacheKye = Constants.RedisKey.ORDER_STAFF_STOCK;
        RBlockingQueue<OrderStaffEntity> blockingQueue = redissonService.getBlockingQueue(cacheKye);
        RDelayedQueue<OrderStaffEntity> delayedQueue = redissonService.getDelayedQueue(blockingQueue);
        delayedQueue.offer(orderStaffEntity, 3, TimeUnit.SECONDS);
    }

    @Transactional
    @Override
    public Collection<Object> takeOrderFromGuard(OrderEntity orderEntity) {
        String cacheKey = Constants.RedisKey.STAFF_ORDER + Constants.UNDERLINE + orderEntity.getRidgepole() + Constants.UNDERLINE + orderEntity.getEnd();
        return redissonService.getScoreSortedSet(cacheKey);
    }

    @Override
    public Collection<Object> getOrderInfoList(OrderEntity build) {
        String cacheKey = Constants.RedisKey.STAFF_ORDER + Constants.UNDERLINE + build.getSorter2();
        log.info("StringCacheKey:{}", cacheKey);
        return redissonService.getScoreSortedSet(cacheKey);
    }

    @Override
    public void removeSortedSetOrderInfo(Long orderId, String staffKey) {
        String cacheKey = Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderId;
        OrderStatusVO orderStatusVO = redissonService.getValue(cacheKey);
        redissonService.deleteSortedSet(orderStatusVO, staffKey);
    }

    @Override
    public OrderStatusVO userGetOrderInfo(OrderEntity build) {
        String cacheKey = Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + build.getOrderId();
        return redissonService.getValue(cacheKey);
    }

    @Override
    public List<OrderStatusVO> getUserOrder(String userId, String status) {
        List<Order> list = orderDao.getUserOrder(userId, status);
        List<OrderStatusVO> orderStatusVOList = new ArrayList<>();
        for (Order order : list) {
            OrderStatusVO orderStatusVO = new OrderStatusVO();
            BeanUtils.copyProperties(order, orderStatusVO);
            orderStatusVOList.add(orderStatusVO);
        }
        return orderStatusVOList;
    }

    @Override
    public boolean judgeOrder(OrderJudgeEntity orderJudgeEntity) {
        int res = judgeDao.getJudge(orderJudgeEntity);
        if (0 != res) {
            return false;
        }
        return 0 != judgeDao.insert(orderJudgeEntity);
    }

    @Override
    public void updateOrderStatus(OrderEntity order) {
        redissonService.decr(Constants.RedisKey.ORDER_NUMBER);
        redissonService.remove(Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + order.getOrderId());
        orderDao.updateOrderStatus(order);
    }

    @Override
    public OrderStatusVO getOrderInfoAndDelete(OrderEntity build) {
        String cacheKey = Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + build.getOrderId();
        OrderStatusVO orderStatusVO = redissonService.getValue(cacheKey);
        redissonService.remove(cacheKey);
        return orderStatusVO;
    }

    @Override
    public String getUserRole(String userId) {
        Staff staff = staffDao.getStaff(userId);
        if (null != staff) {
            return staff.getRole();
        }
        return "user";
        // TODO: 2024/5/21 完善用户角色之间的切换功能，就是用户到员工角色之间的切换
    }


    @Override
    public void UpdateStaff() {
        staffDao.updateStaff();
        staffDao.updateWeather();
    }

    @Override
    public void deleteStaff() {
        staffDao.deleteStaff();
    }

    @Override
    public StaffEntity queryStaffById(String sorter1) {
        Staff staff = staffDao.getStaff(sorter1);
        StaffEntity staffEntity = new StaffEntity();
        BeanUtils.copyProperties(staff, staffEntity);
        return staffEntity;
    }

    @Override
    public boolean checkKey(String id, String ridgepole) {
        String staffKey = Constants.RedisKey.STAFF_KEY + id;
        boolean res = redissonService.isExists(staffKey);
        if (!res) {
            redissonService.setValue(staffKey, ridgepole);
            return true;
        }
        String value = redissonService.getValue(staffKey);
        return ridgepole.equals(value);
    }

    @Override
    public void deleteStaffKey(String sorter1) {
        redissonService.remove(Constants.RedisKey.STAFF_KEY + sorter1);
    }

    @Override
    public String getOrderNumber() {
        Integer res = redissonService.getValue(Constants.RedisKey.ORDER_NUMBER);
        return String.valueOf(res);
    }

    @Override
    public Map<StaffEntity, List<OrderStaffEntity>> updateSalary() {
        List<Staff> staffList = staffDao.queryStaffList();
        Map<StaffEntity, List<OrderStaffEntity>> map = new HashMap<>();
        for (Staff staff : staffList) {
            List<OrderStaff> orderStaffList = orderStaffDao.queryTodayOrderStaff(staff.getStaffId(), TimeUtil.getDayTime());
            List<OrderStaffEntity> orderStaffEntities = new ArrayList<>();
            BeanUtils.copyProperties(orderStaffList, orderStaffEntities);
            StaffEntity staffEntity = new StaffEntity();
            BeanUtils.copyProperties(staff, staffEntity);
            map.put(staffEntity, orderStaffEntities);
        }
        return map;
    }

    /**
     * 将订单放入延时队列中
     */
    @Override
    public void addOrderInfo(OrderStatusVO orderStatusVO) {
        orderStatusVO.setStatus(DefaultFactory.Status.CREATE.getInfo());
        String cacheKye = Constants.RedisKey.ORDER_DELAY_QUEUE;
        RBlockingQueue<OrderStatusVO> blockingQueue = redissonService.getBlockingQueue(cacheKye);
        RDelayedQueue<OrderStatusVO> delayedQueue = redissonService.getDelayedQueue(blockingQueue);
        delayedQueue.offer(orderStatusVO, 2, TimeUnit.SECONDS);
    }

    @Override
    public OrderStatusVO takeOrderInfo() {
        String cacheKey = Constants.RedisKey.ORDER_DELAY_QUEUE;
        RBlockingQueue<OrderStatusVO> queue = redissonService.getBlockingQueue(cacheKey);
        OrderStatusVO orderStatusVO = queue.poll();
        if (orderStatusVO != null) {
            String lockKey = Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderStatusVO.getOrderId();
            OrderStatusVO orderInfo = redissonService.getValue(lockKey);
            //判断订单状态是否为支付成功状态，订单只有支付成功了才能放进延时队列里
            if (orderInfo.getStatus().equals(DefaultFactory.Status.PAY.getInfo())) {
                return orderStatusVO;
            }
            return null;
        }
        return null;
    }

    @Override
    public String getStaffIdByRidgepole(String ridgepole) {
        Staff staff = staffDao.getStaffIdByRidgepole(ridgepole);
        if (null == staff) {
            return null;
        }
        return staff.getStaffId();
    }

    /**
     * 将订单状态设置为错误（没有骑手就会出现这个错误），并加入延时队列，2分钟后重新分配
     */
    @Override
    public void setOrderError(Long orderId) {
        String cacheKey = Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderId;
        OrderStatusVO orderStatusVO = redissonService.getValue(cacheKey);
        orderStatusVO.setStatus(DefaultFactory.Status.NO_SORTER.getInfo());
        redissonService.setValue(cacheKey, orderStatusVO);
        orderDao.setOrderError(orderId, DefaultFactory.Status.FAIL_NO_ORDER.getInfo());
        addOrderInfo(orderStatusVO);
    }

    @Override
    public void updateDailySalary(List<StaffSalaryEntity> salaryEntities) {
        for (StaffSalaryEntity salary : salaryEntities) {
            StaffSalary staffSalary = new StaffSalary();
            BeanUtils.copyProperties(salary, staffSalary);
            staffSalaryDao.updateSalary(staffSalary);
        }
    }

    @Override
    public String setWeather(String userId, String weather) {
        staffDao.setWeather(userId, weather);
        return weather;
    }

    // TODO: 2024/5/30 委托方并没有具体说明评价板块的开发功能，且当前需求修改太多时间即将截止，评价功能等委托方完善需求之后在做优化
    @Override
    public List<JudgeRes> getBadJudge(String type) {
        List<Judge> res = judgeDao.getBadJudge(type);
        List<JudgeRes> ans = new ArrayList<>();
        for (Judge judge : res) {
            String userName = userDao.queryUserNameById(judge.getUserId()).getUserName();
            JudgeRes judgeRes = JudgeRes.builder().orderId(judge.getOrderId()).picture(judge.getPicture()).info(judge.getInfo()).type(judge.getType()).userName(userName).build();
            List<OrderStaff> list = orderStaffDao.getOrderStaff(judge.getOrderId());
            for (OrderStaff orderStaff : list) {
                if ("sorter1".equals(orderStaff.getStaffRole())) {
                    judgeRes.setSorter1Name(orderStaff.getStaffName());
                    judgeRes.setSorter1Phone(orderStaffDao.getStaffPhoneNumber(orderStaff.getStaffId()).getPhoneNumber());
                } else if ("guard".equals(orderStaff.getStaffRole())) {
                    judgeRes.setGuardName(orderStaff.getStaffName());
                    judgeRes.setGuardPhone(orderStaffDao.getStaffPhoneNumber(orderStaff.getStaffId()).getPhoneNumber());
                } else {
                    judgeRes.setSorter2Name(orderStaff.getStaffName());
                    judgeRes.setSorter2Phone(orderStaffDao.getStaffPhoneNumber(orderStaff.getStaffId()).getPhoneNumber());
                }
            }
            ans.add(judgeRes);
        }
        return ans;
    }

    @Override
    public Map<String, Integer> getSorter1Staff(OrderEntity order) {
        DepartmentGroup departmentGroup = departmentGroupDao.getSorter1Staff(order);
        Map<String, Integer> map = new HashMap<>();
        map.put("main", departmentGroup.getMainLimit() - departmentGroup.getMainStaff());
        map.put("minor", departmentGroup.getMinorLimit() - departmentGroup.getMinorStaff());
        return map;
    }

    @Override
    public Map<String, Integer> getGuardStaff(OrderEntity order) {
        Department department = departmentDao.getGuardStaff(order);
        Map<String, Integer> map = new HashMap<>();
        map.put("main", department.getMainLimit() - department.getMainStaff());
        map.put("minor", department.getMinorLimit() - department.getMinorStaff());
        return map;
    }

    @Override
    public Map<String, Integer> getSorter2Staff(OrderEntity order) {
        Floor floor = floorDao.getSorter2Staff(order, Integer.parseInt(order.getEnd()));
        Map<String, Integer> map = new HashMap<>();
        map.put("main", floor.getMainLimit() - floor.getMainStaff());
        map.put("minor", floor.getMinorLimit() - floor.getMinorStaff());
        return map;
    }

    @Override
    @Transactional
    public boolean beSorter1(StaffEntity staffEntity) {

        int res;
        Integer group = getGroupId(staffEntity.getRidgepole());
        staffEntity.setGroupId(group);
        if ("main".equals(staffEntity.getType())) {
            res = departmentGroupDao.beMainSorter1(staffEntity);
        } else {
            res = departmentGroupDao.beMinorSorter1(staffEntity);
        }
        Staff staff = staffDao.getStaff(staffEntity.getStaffId());
        userDao.setFirstLogin(staffEntity.getStaffId());
        log.info("staff:{}", staff);
        staffDao.deleteStaffIdById(staffEntity.getStaffId());
        staffEntity.setPhoneNumber(staff.getPhoneNumber());
        staffEntity.setPayAccount(staff.getPayAccount());
        staffEntity.setPayNickName(staff.getPayNickName());
        staffEntity.setStaffName(staff.getStaffName());
        log.info("staffEntity:{}", staffEntity);
        return staffDao.insert(staffEntity) != 0 && res != 0;
    }

    @Override
    public boolean checkStaff(StaffEntity staffEntity) {
        DepartmentGroup departmentGroup = departmentGroupDao.getSorter1StaffByDepartmentGroup(OrderEntity.builder()
                .ridgepole(staffEntity.getRidgepole())
                .build());
        boolean res = false;
        if ("main".equals(staffEntity.getType())) {
            res = departmentGroup.getMainStaff() >= departmentGroup.getMainLimit();
        } else {
            res = departmentGroup.getMinorStaff() >= departmentGroup.getMinorLimit();
        }
        return staffDao.checkStaff(staffEntity) != null || res;
    }

    @Override
    public Integer getGroupId(String department) {
        return departmentDao.getGroupId(department).getGroup();
    }

    @Override
    public boolean checkGuard(StaffEntity staffEntity) {
        Department department = departmentDao.getGuardStaff(OrderEntity.builder()
                .ridgepole(staffEntity.getRidgepole())
                .build());
        log.info("department:{}", department);
        boolean res = false;
        if ("main".equals(staffEntity.getType())) {
            res = department.getMainLimit() <= department.getMainStaff();
        } else {
            res = department.getMinorLimit() <= department.getMinorStaff();
        }
        if (res) {
            log.info("满员了");
        }
        return staffDao.checkStaff(staffEntity) != null || res;
    }

    @Override
    @Transactional
    public boolean beGuard(StaffEntity staffEntity) {
        int res;
        if ("main".equals(staffEntity.getType())) {
            res = departmentDao.beMainGuard(staffEntity);
        } else {
            res = departmentDao.beMinorGuard(staffEntity);
        }
        userDao.setFirstLogin(staffEntity.getStaffId());
        Staff staff = staffDao.getStaff(staffEntity.getStaffId());
        log.info("staff:{}", staff);

        staffDao.deleteStaffIdById(staffEntity.getStaffId());

        staffEntity.setPhoneNumber(staff.getPhoneNumber());
        staffEntity.setPayAccount(staff.getPayAccount());
        staffEntity.setPayNickName(staff.getPayNickName());
        staffEntity.setStaffName(staff.getStaffName());

        log.info("staffEntity:{}", staffEntity);
        return staffDao.insert(staffEntity) != 0 && res != 0;
    }

    @Override
    public boolean checkSorter2(StaffEntity staffEntity) {
        log.info("staffEntity:{}", staffEntity);
        Floor floor = floorDao.getSorter2StaffByValue(OrderEntity.builder()
                .ridgepole(staffEntity.getRidgepole())
                .build(), staffEntity.getValue());
        log.info("floor:{}", floor);
        boolean res = false;
        if ("main".equals(staffEntity.getType())) {
            res = floor.getMainStaff() >= floor.getMainLimit();
        } else {
            res = floor.getMinorStaff() >= floor.getMinorLimit();
        }
        log.info("res:{}", res);
        return staffDao.checkStaff(staffEntity) != null || res;
    }

    @Override
    @Transactional
    public boolean beSorter2(StaffEntity staffEntity) {
        int res;
        if ("main".equals(staffEntity.getType())) {
            res = floorDao.beMainSorter2(staffEntity, staffEntity.getFloor());
        } else {
            res = floorDao.beMinorSorter2(staffEntity, staffEntity.getFloor());
        }
        Staff staff = staffDao.getStaff(staffEntity.getStaffId());
        userDao.setFirstLogin(staffEntity.getStaffId());
        log.info("staff:{}", staff);
        staffDao.deleteStaffIdById(staffEntity.getStaffId());
        staffEntity.setPhoneNumber(staff.getPhoneNumber());
        staffEntity.setPayAccount(staff.getPayAccount());
        staffEntity.setPayNickName(staff.getPayNickName());
        staffEntity.setStaffName(staff.getStaffName());
        log.info("staffEntity:{}", staffEntity);
        return staffDao.insert(staffEntity) != 0 && res != 0;
    }

    /**
     * 用户支付成功回调函数将订单放入对应的骑手的延时队列
     *
     * @param orderId 订单号
     */
    @Override
    public void setOrderPayEd(Long orderId) {

        OrderStatusVO orderStatusVO = redissonService.getValue(Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderId);
        if (DefaultFactory.Status.PAY.getInfo().equals(orderStatusVO.getStatus())) {
            return;
        }
        orderStatusVO.setStatus(DefaultFactory.Status.PAY.getInfo());
        DepartmentGroup departmentGroup = departmentGroupDao.getDepartmentByRidgepole(orderStatusVO.getRidgepole());
        log.info("departmentGroup:{}", departmentGroup.getDepartmentInfo());
        String time=TimeUtil.getDayTime().substring(0,7);
        redissonService.incrBy(Constants.RedisKey.MothSalary+Constants.UNDERLINE+time, orderStatusVO.getPrice());
        redissonService.incrBy(Constants.RedisKey.ALLSalary, orderStatusVO.getPrice());
        redissonService.addObjectToSortedSet(Constants.RedisKey.SORTEDSET_DEPARTMENT + Constants.UNDERLINE + departmentGroup.getDepartmentInfo(), orderStatusVO);
        //更新redis缓存
        redissonService.setValue(Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderId, orderStatusVO);
        //用户支付成功之后才能将订单信息放入对应的延时队列里
        addOrderInfo(orderStatusVO);
        redissonService.incr(Constants.RedisKey.ORDER_NUMBER);
    }

    @Override
    public boolean setLocation(UserEntity entity) {
        log.info("userEntity:{}", entity);
        userDao.setFirstLogin(entity.getUserId());
        return userDao.updateUserInfo(entity.getUserId(),
                entity.getNickName(),
                entity.getUserName(),
                entity.getRidgepole()
                , entity.getFloor()
                , entity.getRoomNumber()
                , entity.getPhoneNumber()) != 0;
    }

    @Override
    public StaffEntity registerToStaff(StaffEntity staffEntity) {
        userDao.setFirstLogin(staffEntity.getStaffId());
        int res = userDao.setUserToStaff(staffEntity.getStaffId());
        log.info("修改用户角色{}", res != 0);
        Staff staff = staffDao.getStaff(staffEntity.getStaffId());
        if (null != staff) {
            log.info("staff表有这个用户");
            return null;
        }
        staffEntity.setStatus("-3");
        log.info("插入员工:{}", staffEntity);
        if (staffDao.insert(staffEntity) == 0) return null;
        return staffEntity;
    }

    @Override
    public List<OrderStatusVO> getWaitPaySet() {
        String cacheKey = Constants.RedisKey.WAIT_PAY_ORDER;
        Collection<Object> scoreSortedSetAndDelete = redissonService.getScoreSortedSetAndDelete(cacheKey);
        List<OrderStatusVO> ans = new ArrayList<>();
        for (Object o : scoreSortedSetAndDelete) {
            OrderStatusVO orderStatusVO = new OrderStatusVO();
            BeanUtils.copyProperties(o, orderStatusVO);
            log.info("orderStatusVO,id:{},department:{}", orderStatusVO.getOrderId(), orderStatusVO.getRidgepole());
            ans.add(orderStatusVO);
        }
        return ans;
    }

    @Override
    public List<DepartRes> getDepartmentGroup() {
        List<DepartmentGroup> ans = departmentGroupDao.getAll();
        List<DepartRes> list = new ArrayList<>();
        for (DepartmentGroup departmentGroup : ans) {
            DepartRes depart = DepartRes.builder()
                    .label(departmentGroup.getLabel())
                    .value(departmentGroup.getDepartmentInfo())
                    .build();
            list.add(depart);
        }
        return list;
    }

    @Override
    public List<OrderStatusVO> getOrderByNumber(Integer number, String ridgepole) {
        String key = Constants.RedisKey.SORTEDSET_DEPARTMENT + Constants.UNDERLINE + ridgepole;
        Collection<Object> sortedSetByNumber = redissonService.getSortedSetByNumber(key, number);
        Object[] array = sortedSetByNumber.toArray();
        List<OrderStatusVO> list = new ArrayList<>();
        if (number > array.length) return null;
        for (int i = 0; i < number; i++) {
            OrderStatusVO orderStatusVO = new OrderStatusVO();
            BeanUtils.copyProperties(array[i], orderStatusVO);
            list.add(orderStatusVO);
        }
        return list;
    }

    @Transactional
    @Override
    public String getStaffNameById(String guardId) {
        return staffDao.getStaff(guardId).getStaffName();
    }

    @Override
    public String getFloor(String ridgepole, Integer floor) {
        Floor dFloor = floorDao.getFloor(ridgepole, floor);
        return dFloor.getFrom() + Constants.UNDERLINE + dFloor.getTo();
    }

    @Override
    public void deleteOrderFromDepartment(Long orderId, String ridgepole, String end) {
        String cacheKey = Constants.RedisKey.STAFF_ORDER + Constants.UNDERLINE + ridgepole + Constants.UNDERLINE + end;
        OrderStatusVO statusVO = redissonService.getValue(Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderId);
        log.info("删除订单key:{},value:{}", cacheKey, statusVO);
        redissonService.deleteSortedSet(statusVO, cacheKey);
    }

    @Override
    public List<String> getPosition() {
        List<Positions> list = positionDao.getAll();
        List<String> ans = new ArrayList<>();
        for (Positions positions : list) {
            ans.add(positions.getPosition());
        }
        return ans;
    }

    @Override
    public List<FloorRes> getFloorByRidgepole(String ridgepole) {
        List<Floor> list = floorDao.getFloorByRidgepole(ridgepole);
        List<FloorRes> ans = new ArrayList<>();
        for (Floor floor : list) {
            FloorRes floorRes = FloorRes.builder()
                    .value(floor.getValue())
                    .build();
            ans.add(floorRes);
        }
        return ans;
    }

    @Override
    public String getStaffIdByName(String sorter1) {
        Staff idByName = staffDao.getIdByName(sorter1);
        return idByName.getStaffId();
    }

    @Override
    public void deleteStaffOrderInfo(String sorter1Id, OrderStatusVO orderStatusVO) {
        String key = Constants.RedisKey.ORDER_STAFF_INFO + Constants.UNDERLINE + sorter1Id;
        redissonService.deleteSortedSet(orderStatusVO, key);
    }

    @Override
    public String getRidgepoleById(String guard) {
        return staffDao.getStaff(guard).getRidgepole();
    }

    @Override
    public StaffRes getStaff(String staffId) {
        Staff staff = staffDao.getStaff(staffId);
        StaffRes staffRes = new StaffRes();
        if (null == staff) {
            staffRes.setRole("student");
            return staffRes;
        }
        BeanUtils.copyProperties(staff, staffRes);
        return staffRes;
    }

    @Override
    public JudgeOfProblemRes problem(UserEntity userEntity) {
        judgeDao.addProblem(userEntity);
        return JudgeOfProblemRes.builder()
                .judgeId(userEntity.getJudgeId())
                .userId(userEntity.getUserId())
                .info(userEntity.getInfo())
                .build();
    }

    @Override
    public boolean updateProlemPicture(String judgeId, String image) {
        return judgeDao.updateProblem(judgeId, image) != 0;
    }

    @Override
    public boolean setPost(UserEntity user) {
        return userDao.setPost(user) != 0;
    }

    @Override
    public void getAllOrder(OrderEntity build) {
        List<Order> list = orderDao.getAllUserOrder(build);

    }

    @Override
    public Long getAllSalary() {
        Long salary = redissonService.getValue(Constants.RedisKey.ALLSalary);
        if (null == salary || salary == 0) {
            salary = orderDao.getAllSalary();
            redissonService.setValue(Constants.RedisKey.ALLSalary, salary);
            return salary;
        }
        return salary;
    }


    // TODO: 2024/6/23获取当前月份的总收入
    // TODO: 2024/7/8 添加一个每月的定时任务清理每月收入并添加新的月份将值置为0
    @Override
    public Long getMonthSalary() {
        String time = TimeUtil.getDayTime().substring(0,7);
        Long salary = redissonService.getValue(Constants.RedisKey.MothSalary+Constants.UNDERLINE+time);
//        if (null == salary || salary == 0) {
//            salary=0L;
//            List<Order> list=orderDao.getAllOrder();
//            for(Order order:list){
//                String orderTime=order.getDayTime().substring(0,7);
//                if(orderTime.equals(time)){
//                    salary+=order.getPrice();
//                }
//            }
//            redissonService.setValue(Constants.RedisKey.MothSalary,salary);
//        }
        return salary;
    }

    @Override
    public Integer getUserNumber() {
        return userDao.getUserNumber();
    }

    @Override
    public Integer getMothUser() {
        String dayTime=TimeUtil.getDayTime().substring(0,7);
        return userDao.getMothUser(dayTime);
    }

    @Override
    public Long getAllMoney() {
         Long ans=staffSalaryDao.getAllSalary();
         return getAllSalary()-ans;
    }

    @Override
    public Long getMothMoney() {
        String time=TimeUtil.getDayTime().substring(0,7);
        Long ans=staffSalaryDao.getMothSalary(time);
        return getMonthSalary()-ans;
    }

    @Override
    public Long getAllOutcome() {
        return staffSalaryDao.getAllSalary();
    }

    @Override
    public Long getMothOutcome() {
        String time=TimeUtil.getDayTime();
        return staffSalaryDao.getMothSalary(time);
    }

    @Override
    public List<MUserRes> getAllUsers() {
        List<MUser> list=imUserDao.getAllUsers();
        List<MUserRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }

    @Override
    public void setMothTime() {
        redissonService.setValue(Constants.RedisKey.MothSalary+Constants.UNDERLINE+TimeUtil.getDayTime().substring(0,7),0);
    }

    @Override
    public List<MUserRes> getUserBy(MUserEntity build) {
        List<MUser> list=imUserDao.getUserBy(build);
        List<MUserRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }

    @Override
    public List<MRiderRes> getAllRider() {
        List<MRider> list=orderDao.getAllRiderBySorter1();
        List<MRiderRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }

    @Override
    public List<MRiderRes> getRiderBy(MRiderEntity build) {
        List<MRider> list=orderDao.getRiderBy(build);
        List<MRiderRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }

    @Override
    public List<MGuardRes> getAllGuard() {
        List<MGuard> list=orderDao.getAllGuard();
        List<MGuardRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }

    @Override
    public List<MGuardRes> getGuardBy(MGuardEntity build) {
        List<Guard> list=orderDao.getGUardBy(build);
        List<MGuardRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }

    @Override
    public List<MSorterRes> getAllSorter() {
        List<MSorter> list=orderDao.getAllSorter();
        List<MSorterRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }

    @Override
    public List<MSorterRes> getSorterBy(MSorterEntity build) {
        List<MSorter> list=orderDao.getSorterBy(build);
        List<MSorterRes> ans=new ArrayList<>();
        BeanUtils.copyProperties(list,ans);
        return ans;
    }


    @Override
    @Transactional
    public Boolean updateOrder(OrderStatusVO orderStatusVO, String staffKey, String staffId) {

        String cacheKey = Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderStatusVO.getOrderId();
        String phoneNumber = staffDao.getStaffPhoneNumber(staffId).getPhoneNumber();
        String orderStaffKey = Constants.RedisKey.ORDER_STAFF_INFO + Constants.UNDERLINE + staffId;
        orderStatusVO.setPhoneNumber(phoneNumber);
        redissonService.addToSortedSet(orderStaffKey, orderStatusVO);
        redissonService.setValue(cacheKey, orderStatusVO);

        if (null != staffKey) {
            redissonService.addToSortedSet(staffKey, orderStatusVO);
        }
        if (staffId == null) {
            return true;
        }
        return orderStaffDao.insertOrderStaff(orderStatusVO.getOrderId(), staffId, orderStatusVO.getStaffName(), orderStatusVO.getStatusCode(), orderStatusVO.getDistance(), TimeUtil.getDayTime()) != 0;
    }

    @Override
    public String queryUserNameById(String id) {
        return userDao.queryUserNameById(id).getUserName();
    }

    @Override
    public Object[] getTokenOrder(OrderEntity orderEntity) {
        String cacheKey = Constants.RedisKey.ORDER_STAFF_INFO + Constants.UNDERLINE + orderEntity.getSorter1();
        RScoredSortedSet<Order> sortedSet = redissonService.getSortedSet(cacheKey);
        Object[] array = sortedSet.toArray();
        return array;
    }

    @Override
    public Collection<Object> getOrderByQRCode(OrderEntity orderEntity) {
        String cacheKey = Constants.RedisKey.STAFF_ORDER + Constants.UNDERLINE + orderEntity.getSorter1() + Constants.UNDERLINE + orderEntity.getRidgepole();
        Collection<Object> scoreSortedSet = redissonService.getScoreSortedSetAndDelete(cacheKey);
        log.info("OrderStatusVO[]:{}", scoreSortedSet);
        return scoreSortedSet;
    }

    @Override
    public Collection<Object> queryGuardOrder(OrderEntity orderEntity) {
        String ridgepole = getRidgepoleById(orderEntity.getGuard());
        Floor floor = floorDao.getFloorByRidgepoleAndValue(ridgepole, orderEntity.getEnd());
        String end = floor.getFrom() + Constants.UNDERLINE + floor.getTo();
        String cacheKey = Constants.RedisKey.STAFF_ORDER + Constants.UNDERLINE + ridgepole + Constants.UNDERLINE + end;
        return redissonService.getScoreSortedSet(cacheKey);
    }

    @Override
    public OrderRes takeOrder(OrderEntity order) {
        return null;
    }

    @Override
    public void saveUserImage(String url, String userId) {
        userDao.updateUserImage(userId, url);
    }

    @Override
    public List<DepartmentRes> getDepartment() {
        return departmentDao.getDepartment();
    }

    @Override
    public Boolean saveOrderInfoPicture(Long orderId, String url) {
        String cacheKey = Constants.RedisKey.ORDER_INFO + Constants.UNDERLINE + orderId;
        OrderStatusVO order = redissonService.getValue(cacheKey);
        order.setOrderInfoPicture(url);
        redissonService.setValue(cacheKey, order);
        int res = orderDao.saveOrderInfoPicture(orderId, url);
        return 0 != res;
    }

    @Override
    public Integer judgeRoute(String start, String ridgepole) {
        return route.judge(start, ridgepole);
    }

    @Override
    public DepartmentRes getDepartmentAndFloor(String ridgepole) {
        Department department = departmentDao.getDepartmentAndFloor(ridgepole);
        return (department == null) ? null : DepartmentRes.builder().departmentGroup(departmentGroupDao.getDepartment(department.getGroup()).getDepartmentInfo()).floor(department.getFloor()).department(ridgepole).group(department.getGroup()).build();
    }
}